package dota.entity;

import gameframework.base.Drawable;
import gameframework.base.Overlappable;
import gameframework.game.GameEntity;
import gameframework.game.GameMovable;
import gameframework.game.MoveBlocker;
import gameframework.game.SpriteManager;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import dota.ImageManager;
import dotaframework.game.DotaGameMovableDriver;
import dotaframework.game.DotaSpriteManager;
import dotaframework.game.MoveStrategyMultipleGoal;
import dotaframework.utils.*;
import dotaframework.weapon.SoldierArmed;

public class ArmedUnitSoldier extends GameMovable implements
ArmedUnit , Drawable, GameEntity, Overlappable, MoveBlocker {
	protected Soldier soldier;
	protected List<String> equipments = new ArrayList<String>();
	protected AgeFactory age;

	private SpriteManager spriteManager;
	private MoveBlocker blocker;

	public ArmedUnitSoldier(AgeFactory factory, String soldatType, String name, int img){
		this.age = factory;
		String methodName = "get" + soldatType + "Soldier";
		try {
			Method method = factory.getClass().getMethod(methodName,
					String.class);
 			soldier = (SoldierAbstract) method.invoke(factory, name);
		} catch (Exception e) {
			throw new UnknownSoldierTypeException("Unknown soldier type"
					+ e.toString());
		}
		spriteManager = new DotaSpriteManager(ImageManager.getImage(img),
				ImageManager.getSizeX(img), ImageManager.getSizeY(img), 3, 5);
		spriteManager.setTypes(ImageManager.getSpriteTypes(img));
		blocker = null;
	}

	public boolean addEquipment(String equipmentType) {
		if (alive()) { // XXX "else" not treated
			if (equipments.contains(equipmentType)) {
				return false; // decoration not applied
			} else {
				String[] splitedEquipType = equipmentType.split(":");
				String methodName = "get" + splitedEquipType[0] + "Weapon";
				try {
					Method method = age.getClass().getMethod(methodName,
							Soldier.class, String.class);
					soldier = (Soldier) method.invoke(age, soldier, splitedEquipType[1]);
					equipments.add(equipmentType);
					System.out.println(equipmentType + " added");
				} catch (Exception e) {
					throw new RuntimeException("Unknown equipment type "
							+ e.toString());
				}
			}
		}
		return true;
	}

	public String getName() {
		return soldier.getName();
	}

	public float getHealthPoints() {
		return soldier.getHealthPoints();
	}

	public AgeFactory getAge() {
		return age;
	}

	public boolean alive() {
		return soldier.alive();
	}

	public void heal() {
		soldier.heal();
	}
	
	public void levelUp()
	{
		Soldier soldierToLvlUp = soldier;
		while ( soldierToLvlUp instanceof SoldierArmed )
		{
			soldierToLvlUp = ((SoldierArmed)soldierToLvlUp).getSoldier();
		}
		
		if ( soldierToLvlUp instanceof Horseman )
		{
			System.out.println("Level up !");
			((Horseman) soldierToLvlUp).setInitialHealthPoints(Horseman.getMAXHEALTHPOINTS()+100);
			((Horseman) soldierToLvlUp).setMAXHEALTHPOINTS(Horseman.getMAXHEALTHPOINTS()+100);
			soldierToLvlUp.heal();
		}

	}

	public float strike() {
		return soldier.strike();
	}

	public boolean parry(float force) {
		//notify(this);
		return soldier.parry(force);
	}

	public void accept(VisitorClassicForArmedUnit v) {
		v.visit(this);
	}

	public <T> T accept(VisitorFunForArmedUnit<T> v) {
		return v.visit(this);
	}

	@Override
	public Rectangle getBoundingBox() {
		return new Rectangle(getPosition().x, getPosition().y, ((DotaSpriteManager)spriteManager).getSpriteSizeX(), ((DotaSpriteManager)spriteManager).getSpriteSizeY());
	}

	@Override
	public void draw(Graphics g) {
		String spriteType = "";
		Point tmp = getSpeedVector().getDirection();

		if (tmp.getX() == 1) {
			spriteType += "right";
		} else if (tmp.getX() == -1) {
			spriteType += "left";
		} else if (tmp.getY() == 1) {
			spriteType += "down";
		} else if (tmp.getY() == -1) {
			spriteType += "up";
		} else {
			spriteType = "static";
			spriteManager.reset();
		}
		spriteManager.setType(spriteType);
		spriteManager.draw(g, getPosition());
		
		
		//Drawing life bar frame
		int barWidth = getBoundingBox().width;
		
		g.setColor(Color.BLACK);
		g.drawRect(getPosition().x, getPosition().y-10, barWidth, 5);
		
		
		float LifePercentage = soldier.getHealthPoints()/soldier.getInitialHealthPoints();

		//GREEN = high life, YELLOW = middle life, RED = low life
		if ( LifePercentage > 0.63 )
			g.setColor(Color.GREEN);
		else if ( LifePercentage > 0.33 )
			g.setColor(Color.YELLOW);
		else
			g.setColor(Color.RED);

		//Drawing life bar inside
		g.fillRect(getPosition().x+1, getPosition().y-9, (int) ((barWidth-1)*LifePercentage), 4);
		
	}

	@Override
	public void oneStepMoveAddedBehavior() {
		spriteManager.increment();
		if(((DotaGameMovableDriver)getDriver()).getStrategy() instanceof MoveStrategyMultipleGoal)
			((MoveStrategyMultipleGoal)((DotaGameMovableDriver)getDriver()).getStrategy()).setPosition(getPosition());
	}

	public void setBlocker(MoveBlocker moveBlocker) {
		blocker = moveBlocker;
	}

	public ArmedUnit getBlocker() {
		return (ArmedUnit) blocker;
	}

}
